package com.chenfan.mcn.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chenfan.common.exception.BusinessException;
import com.chenfan.common.utils.DateUtils;
import com.chenfan.mcn.clients.baseinfo.BaseCustomer;
import com.chenfan.mcn.clients.baseinfo.BaseInfoClient;
import com.chenfan.mcn.clients.finance.ClearData4ExecuteOrderVo;
import com.chenfan.mcn.clients.finance.FinanceClient;
import com.chenfan.mcn.clients.privilege.*;
import com.chenfan.mcn.constant.BillCodeCst;
import com.chenfan.mcn.constant.DictTypeCst;
import com.chenfan.mcn.constant.McnConstant;
import com.chenfan.mcn.constant.NumberCst;
import com.chenfan.mcn.dao.*;
import com.chenfan.mcn.enums.*;
import com.chenfan.mcn.exception.McnErrorCode;
import com.chenfan.mcn.component.CodeGenerateHelper;
import com.chenfan.mcn.model.*;
import com.chenfan.mcn.model.dto.*;
import com.chenfan.mcn.model.vo.*;
import com.chenfan.mcn.rule.BusinessCommissionRuleContext;
import com.chenfan.mcn.service.*;
import com.chenfan.mcn.utils.BusinessAssert;
import com.chenfan.mcn.extension.excel.ExcelUtils;
import com.chenfan.mcn.utils.CommonUtil;
import com.chenfan.mcn.model.common.PageInfo;
import com.chenfan.mcn.utils.DateUtil;
import com.chenfan.mcn.utils.NoRepeatableArrayList;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 商务提成 服务实现类
 * </p>
 *
 * @author lizhejin
 * @since 2021-06-07
 */
@SuppressWarnings("deprecation")
@Service
@Slf4j
public class BusinessCommissionServiceImpl extends ServiceImpl<BusinessCommissionMapper, BusinessCommission> implements BusinessCommissionService {

    private static final String SEPARATOR = "！";

    @Autowired
    private BusinessCommissionMapper businessCommissionMapper;

    @Autowired
    private BusinessCommissionDetailMapper businessCommissionDetailMapper;

    @Autowired
    private BaseInfoClient baseInfoClient;

    @Autowired
    private BusinessCommissionDetailService businessCommissionDetailService;

    @Autowired
    private ApprovalFlowService approvalFlowService;

    @Autowired
    private PrivilegeClient privilegeClient;

    @Autowired
    private IncomeContractMapper incomeContractMapper;

    @Autowired
    private BusinessCommissionConfirmedMapper businessCommissionConfirmedMapper;

    @Autowired
    private AeQuarterlyTableService aeQuarterlyTableService;

    @Autowired
    private BusinessCommissionDetailTemporaryMapper businessCommissionDetailTemporaryMapper;

    @Autowired
    private DepartmentTargetMapper departmentTargetMapper;

    @Autowired
    private CustomerTargetMapper customerTargetMapper;

    @Autowired
    private BusinessCommissionDetailTemporaryService businessCommissionDetailTemporaryService;

    @Value("${bc.return.earliest-start-date : 2021-09-01 00:00:00}")
    private String earliestStartDateStr;

    @Autowired
    private BusinessCommissionReturnMapper bcReturnMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    private final BigDecimal PERCENT_30 = new BigDecimal("0.3");

    @Autowired
    private FinanceClient financeClient;


    @Autowired
    private StarPlatformInfoService starPlatformInfoService;

    @Autowired
    private ContractExcutionOrderMapper contractExcutionOrderMapper;

    @Autowired
    private BrandInfoService brandInfoService;

    /**
     * 商务提成列表
     *
     * @param page                  {@link McnPage}
     * @param businessCommissionDTO {@link BusinessCommissionDTO}
     * @return
     */
    @Override
    public Page<BusinessCommissionVO> getList(McnPage<BusinessCommissionVO> page, BusinessCommissionDTO businessCommissionDTO) {
        return businessCommissionMapper.getList(page, businessCommissionDTO);
    }

    /**
     * 季度编号下拉选项
     *
     * @return List
     */
    @Override
    public List<String> getQuarterCode() {
        return businessCommissionMapper.getQuarterCode();
    }


    /**
     * 详情
     *
     * @param pageRequest {@link McnPage}
     * @param dto  {@link Long}
     * @return {@link BusinessCommissionInfo}
     */
    @Override
    public BusinessCommissionInfo info(McnPage<BusinessCommissionDetail> pageRequest, BusinessInfoQueryDTO dto) {
        BusinessCommissionInfo commissionInfo = new BusinessCommissionInfo();

        BusinessCommission businessCommission = businessCommissionMapper.selectById(dto.getId());
        BusinessAssert.notNull(businessCommission, McnErrorCode.BUSINESS_COMMISSION_IS_NULL);
        BeanUtils.copyProperties(businessCommission, commissionInfo);
        Page<BusinessCommissionDetailVoV2> iPage = businessCommissionDetailMapper.selectListV2(pageRequest, dto);
        if(CollectionUtils.isNotEmpty(iPage.getRecords())) {
            PageInfo<BusinessCommissionDetailVoV2> pageInfo = PageInfo.toPageInfo(iPage, BusinessCommissionDetailVoV2.class);
            pageInfo.setTotal(iPage.getTotal());
            pageInfo.setPageNum(Long.valueOf(iPage.getCurrent()).intValue());
            pageInfo.setPageSize(Long.valueOf(iPage.getSize()).intValue());
            this.assembleExportData(pageInfo.getList());
            commissionInfo.setBusinessCommissionDetailV2List(pageInfo);
        }

        return commissionInfo;
    }

    @Override
    public void assembleExportData(List<BusinessCommissionDetailVoV2> exportList) {
        if(CollectionUtils.isEmpty(exportList)) {
            return;
        }
        DateFormat dft = new SimpleDateFormat("yyyy-MM-dd");
        List<Long> customerIdList = exportList.stream().map(BusinessCommissionDetailVoV2::getCustomerId).distinct().filter(Objects::nonNull).collect(Collectors.toList());
        Map<Long, BaseCustomer> customerMapping = CommonUtil.getIfNecessary(CollectionUtils.isNotEmpty(customerIdList), () ->
                baseInfoClient.getMcnCustomerByIds(customerIdList).getObj(), Collections.EMPTY_MAP);
        exportList.forEach(x -> {
            if(CommonUtil.containsKey(customerMapping, x.getCustomerId())) {
                x.setCustomerName(customerMapping.get(x.getCustomerId()).getCustomerNameC());
            }
        });
        List<Long> userIdList=new ArrayList<>();
        //设置提成人工号与业绩共享人工号
        List<Long> commissionIdList = exportList.stream().map(BusinessCommissionDetailVoV2::getCommissionId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        if(CollUtil.isNotEmpty(commissionIdList)){
            userIdList.addAll(commissionIdList);
        }
        List<Long> performanceSharerIdList = exportList.stream().map(BusinessCommissionDetailVoV2::getPerformanceSharerId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        if(CollUtil.isNotEmpty(performanceSharerIdList)) {
            userIdList.addAll(performanceSharerIdList);
        }
        List<Long> departmentHeadIdList = exportList.stream().map(BusinessCommissionDetailVoV2::getDepartmentHeadId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        if(CollUtil.isNotEmpty(departmentHeadIdList)) {
            userIdList.addAll(departmentHeadIdList);
        }

        if (CollectionUtils.isNotEmpty(userIdList)) {
            List<SUser> sUserList = privilegeClient.getUserByIds(userIdList).getObj();
            Map<Long, String> sUserNameMap = CommonUtil.getIfNecessary(CollectionUtils.isNotEmpty(sUserList),
                    () -> sUserList.stream().collect(Collectors.toMap(k -> k.getUserId(), v -> v.getJobNumber())), Collections.EMPTY_MAP);
            exportList.forEach(x -> {
                x.setJobNumber(sUserNameMap.get(x.getCommissionId()));
                x.setPerformanceSharerNumber(sUserNameMap.get(x.getPerformanceSharerId()));
                x.setDepartmentJobNumber(sUserNameMap.get(x.getDepartmentHeadId()));
            });
        }

        //设置部门名称
        List<Long> departmentIdList = exportList.stream().map(BusinessCommissionDetailVoV2::getDepartmentId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        if(CollUtil.isNotEmpty(departmentIdList)) {
            Map<Long, SDepartment> sDepartmentMap = privilegeClient.getDepartmentByIds(departmentIdList).getObj();
            exportList.forEach(x -> {
                if (CommonUtil.containsKey(sDepartmentMap, x.getDepartmentId())) {
                    x.setDepartment(sDepartmentMap.get(x.getDepartmentId()).getDepartmentName());
                }
            });
        }
        convertType2Name(exportList);
        List<String> excuteCodes = exportList.stream().map(BusinessCommissionDetailVoV2::getExcuteCode).collect(Collectors.toList());
        Map<String, ClearData4ExecuteOrderVo> clearData4ExecuteOrderMap = financeClient.clearData4ExecuteOrder(excuteCodes).getObj();
        exportList.forEach(x -> {
            x.setContractTypeName(IncomeContractTypeEnum.getContractTypeName(x.getContractType()));
            x.setContractPaybackStatusName(PaybackStatusEnum.getStatusName(x.getContractPaybackStatus()));
            x.setPaybackStatusName(PaybackStatusEnum.getStatusName(x.getPaybackStatus()));
            x.setApprovalStatusName(ExcutionApprovalStatusEnum.getStatusName(x.getApprovalStatus()));
            // 财务数据转换
            ClearData4ExecuteOrderVo clearData4ExecuteOrderVo = clearData4ExecuteOrderMap.get(x.getExcuteCode());
            if (Objects.nonNull(clearData4ExecuteOrderVo)) {
                if (StringUtils.isNotBlank(clearData4ExecuteOrderVo.getArapDate())) {
                    String maxPaybackDate = getMaxClearDate(Arrays.asList(clearData4ExecuteOrderVo.getArapDate().split(",")));
                    if(StringUtils.isNotBlank(maxPaybackDate)) {
                        x.setPaybackDate(maxPaybackDate);
                    }
                }
                if (StringUtils.isNotBlank(clearData4ExecuteOrderVo.getClearDate())) {
                    String maxClearDate = getMaxClearDate(Arrays.asList(clearData4ExecuteOrderVo.getClearDate().split(",")));
                    if (StringUtils.isNotBlank(maxClearDate) && StringUtils.isNotBlank(x.getRealPublishDate())) {
                        x.setPaidAccountPeriod(String.valueOf(DateUtil.getPhaseDifference(x.getRealPublishDate(), maxClearDate, dft)));
                    }
                    x.setClearDate(maxClearDate);
                }
            }
        });
    }

    private String getMaxClearDate(List<String> clearDateStrList) {
        String max = "";
        if (clearDateStrList.size() > 1) {
            for (String cleDateStr : clearDateStrList) {
                int compareTo = max.compareTo(cleDateStr);
                if (compareTo <= 0) {
                    max = cleDateStr;
                }
            }
        } else {
            max = clearDateStrList.get(0);
        }
        return max;
    }

    private void convertType2Name(List<BusinessCommissionDetailVoV2> dataList) {
        if (CollectionUtils.isEmpty(dataList)) {
            return;
        }
        List<Long> customerIdList = dataList.stream().map(BusinessCommissionDetailVoV2::getCustomerId).distinct().collect(Collectors.toList());
        Map<Long, BaseCustomer> customerMapping = Objects.requireNonNull(baseInfoClient.getMcnCustomerByIds(customerIdList)).getObj();
        //查询平台名称
        List<Long> starPlatInfoIds = dataList.stream().map(BusinessCommissionDetailVoV2::getStarPlatformInfoId).collect(Collectors.toList());
        Map<Long, StarPlatformInfo> starPlatformInfoMap = CommonUtil.defaultList(starPlatformInfoService.selectBatchIds(starPlatInfoIds))
                .stream().collect(Collectors.toMap(StarPlatformInfo::getId, Function.identity()));

        List<String> brandCodes = dataList.stream().map(BusinessCommissionDetailVoV2::getBrandName).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        Map<String,String> brandMap = brandInfoService.getBrandMapByCodes(brandCodes);
        Map<String, Map<String, String>> secondlevelDictMap = baseInfoClient.getAllSecondlevelDictMap(DictTypeCst.PUBLISHING_PLATFORM);
        dataList.forEach(x -> {
            if (starPlatformInfoMap.containsKey(x.getStarPlatformInfoId())) {
                StarPlatformInfo starPlatformInfo = starPlatformInfoMap.get(x.getStarPlatformInfoId());
                x.setPlatformName(starPlatformInfo.getPlatformName());
                if (StringUtils.isNotBlank(x.getPublishForm())) {
                    x.setPublishFormName(CommonUtil.getMapValue(secondlevelDictMap.get(starPlatformInfo.getPlatformId()), x.getPublishForm()));
                }
            }
            if(brandMap.containsKey(x.getBrandName())) {
                x.setBrandNameN(brandMap.get(x.getBrandName()));
            }
            if(CommonUtil.containsKey(customerMapping, x.getCustomerId())) {
                x.setCustomerName(customerMapping.get(x.getCustomerId()).getCustomerNameC());
            }
        });
    }

    /**
     * 详情导出excel
     *
     * @param id       商务提成id
     * @param response {@link HttpServletResponse}
     * @throws Exception 抛异常
     */
    @Override
    public void exportExcel(Long id, HttpServletResponse response) {
        BusinessCommission businessCommission = businessCommissionMapper.selectById(id);
        McnPage<BusinessCommissionDetail> page = new McnPage<>();
        //不分页
        page.setPageSize(-1L);
        //不统计总数
        page.setSearchCount(false);
        BusinessInfoQueryDTO dto = new BusinessInfoQueryDTO();
        dto.setId(id);
        List<BusinessCommissionDetailVoV2> businessCommissionDetailV2List = info(page, dto).getBusinessCommissionDetailV2List().getList();
        log.info("商务提成单businessCommissionDetailV2List数据:{}", JSON.toJSONString(businessCommissionDetailV2List));
        String fileName = StringUtils.defaultIfBlank(businessCommission.getTitle(), businessCommission.getQuarterCode() + "商务提成单") + ".xlsx";
        ExcelUtils.exportExcel(businessCommissionDetailV2List, "商务提成", BusinessCommissionDetailVoV2.class, fileName, response);
    }

    /**
     * 新建商务提成
     *
     * @param addDTO {@link BusinessCommissionAddDTO}
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long saveBusinessCommission(BusinessCommissionAddDTO addDTO) {
        BusinessAssert.isTrue(this.baseMapper.notExist(Wrappers.lambdaQuery(BusinessCommission.class).eq(BusinessCommission::getTitle, addDTO.getTitle())
                .ne(BusinessCommission::getBusinessStatus, BusinessCommissionEnum.INVALID.code())), McnErrorCode.BUSINESS_COMMISSION_TITLE_REPEATED);
        BusinessCommission businessCommission = new BusinessCommission();
        BeanUtils.copyProperties(addDTO, businessCommission);
        businessCommission.setBusinessCommissionCode(CodeGenerateHelper.getCode(BillCodeCst.BUSINESS_COMMISSION));
        businessCommissionMapper.insert(businessCommission);
        List<BusinessCommissionDetailTemporary> list = businessCommissionDetailTemporaryMapper.selectList(Wrappers.lambdaQuery(BusinessCommissionDetailTemporary.class)
                .eq(BusinessCommissionDetailTemporary::getTemporaryCode, addDTO.getTemporaryCode()).eq(BusinessCommissionDetailTemporary::getIsDelete, NumberCst.ZERO));
        BusinessAssert.notEmpty(list, McnErrorCode.BUSINESS_ERROR, "不存在明细数据，请查询");
        List<BusinessCommissionDetail> businessCommissionDetailList = new ArrayList<>();
        list.forEach(x -> {
//            if (NumberCst.ZERO.equals(x.getKeyCustomers()) && x.getTargetAchievementRate().compareTo(BigDecimal.ZERO) == 0) {
//                throw new BusinessException(McnErrorCode.DATA_INVALID.code(), "重点客户-目标达成率为0！收入合同编号=" + x.getIncomeCode());
//            }
            BusinessAssert.notNull(x.getDepartmentHeadId(), McnErrorCode.DATA_NOT_FOUND, "获取不到部门负责人！执行单编号=" + x.getExcuteCode());
            BusinessCommissionDetail detail = new BusinessCommissionDetail();
            BeanUtils.copyProperties(x, detail);
            detail.setIsConfirmed(NumberCst.ZERO);
            businessCommissionDetailList.add(detail);
            x.setIsSave(addDTO.getIsSave());
        });
        businessCommissionDetailTemporaryService.updateBatchById(list);
        //获取关联的执行单并更新商务结算状态为结算中
        List<Long> excuteIds = list.stream().map(x -> x.getExcuteId()).collect(Collectors.toList());
        contractExcutionOrderMapper.updateByNoStrategy(Wrappers.<ContractExcutionOrder>lambdaUpdate()
                .set(ContractExcutionOrder::getBusinessCommissionSettleStatus, NumberCst.ONE)
                .in(ContractExcutionOrder::getId, excuteIds));
        businessCommissionDetailList.forEach(x -> x.setBusinessId(businessCommission.getId()));
        businessCommissionDetailMapper.insertBatch(businessCommissionDetailList);

        // 新增部分需要初始化确认信息
        List<BusinessCommissionDetail> commissionDetails = businessCommissionDetailList.stream().filter(CommonUtil.distinctByKey(BusinessCommissionDetail::getCommissionId)).collect(Collectors.toList());
        List<BusinessCommissionDetail> departmentDetails = businessCommissionDetailList.stream().filter(x -> Objects.nonNull(x.getDepartmentHeadId())).filter(CommonUtil.distinctByKey(BusinessCommissionDetail::getDepartmentHeadId)).collect(Collectors.toList());
        this.setDefaultConfirmed(commissionDetails, departmentDetails);
        return businessCommission.getId();
    }

    /**
     * 修改状态
     *
     * @param id             提成id
     * @param businessStatus 状态
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeStatus(Long id, Integer businessStatus) {
        BusinessCommission businessCommission = this.baseMapper.selectById(id);
        List<BusinessCommissionDetail> businessCommissionDetails = businessCommissionDetailMapper.selectList(Wrappers.lambdaQuery(BusinessCommissionDetail.class)
                .eq(BusinessCommissionDetail::getBusinessId, id)
                .eq(BusinessCommissionDetail::getIsDelete, NumberCst.ZERO));
        // List<BusinessCommissionDetail> commissionDetails = businessCommissionDetails.stream().filter(CommonUtil.distinctByKey(BusinessCommissionDetail::getCommissionId)).collect(Collectors.toList());
        // List<BusinessCommissionDetail> departmentDetails = businessCommissionDetails.stream().filter(x -> Objects.nonNull(x.getDepartmentHeadId())).filter(CommonUtil.distinctByKey(BusinessCommissionDetail::getDepartmentHeadId)).collect(Collectors.toList());
        //发送提成单
        // if (businessStatus.equals(BusinessCommissionEnum.HAS_BEEN_SEND.code())) {
        //     // setDefaultConfirmed(commissionDetails, departmentDetails);
        //     if (businessCommissionDetails.size() < 1) {
        //         throw new BusinessException(McnErrorCode.BUSINESS_COMMISSION_DETAIL_IS_NULL);
        //     }
        //     final String title = StringUtils.defaultIfBlank(businessCommission.getTitle() ,businessCommission.getQuarterCode());
        //     if (commissionDetails.size() > 0) {
        //         commissionDetails.forEach(x -> approvalFlowService.sendBusinessNotify(businessCommission.getTenantId(), x.getBusinessId(), x.getIncomeCode(), title,
        //                 ApprovalEnum.BUSINESS_COMMISSION, true, x.getCommissionId(), x.getCommissionName(), NumberCst.ONE));
        //     }
        //     if (departmentDetails.size() > 0) {
        //         departmentDetails.forEach(x -> approvalFlowService.sendBusinessNotify(businessCommission.getTenantId(), x.getBusinessId(), x.getIncomeCode(), title,
        //                 ApprovalEnum.BUSINESS_DEPARTMENT, true, x.getDepartmentHeadId(), x.getDepartmentHeadName(), NumberCst.TWO));
        //     }
        // }
        // if (businessStatus.equals(BusinessCommissionEnum.CONFIRMED.code()) && businessCommissionDetails.size() > 0) {
        //     businessCommissionDetails.forEach(x -> x.setIsConfirmed(NumberCst.ONE));
        //     businessCommissionDetailService.updateBatchById(businessCommissionDetails);
        //
        //     // 更新确认信息
        //     LambdaQueryWrapper<BusinessCommissionConfirmed> queryWrapper = Wrappers.lambdaQuery(BusinessCommissionConfirmed.class)
        //             .eq(BusinessCommissionConfirmed::getBusinessId, id).eq(BusinessCommissionConfirmed::getIsDelete, NumberCst.ZERO);
        //     List<BusinessCommissionConfirmed> businessCommissionConfirmedList = businessCommissionConfirmedMapper.selectList(queryWrapper);
        //     businessCommissionConfirmedList.forEach(businessCommissionConfirmed -> {
        //         businessCommissionConfirmed.setIsConfirmed(NumberCst.ONE);
        //         businessCommissionConfirmed.setConfirmedTime(new Date());
        //         businessCommissionConfirmedMapper.updateById(businessCommissionConfirmed);
        //     });
        // }
        if (businessStatus.equals(BusinessCommissionEnum.INVALID.code())) {
            if (businessCommissionDetails.size() > 0) {
                invalid(businessCommissionDetails);
                //获取关联的执行单并更新商务结算状态为待结算
                List<Long> excuteIds = businessCommissionDetails.stream().map(x -> x.getExcuteId()).collect(Collectors.toList());
                contractExcutionOrderMapper.updateByNoStrategy(Wrappers.<ContractExcutionOrder>lambdaUpdate()
                        .set(ContractExcutionOrder::getBusinessCommissionSettleStatus, 0)
                        .in(ContractExcutionOrder::getId, excuteIds));
            }
        }
        if (businessStatus.equals(BusinessCommissionEnum.ISSUED.code())) {
            if (CollUtil.isNotEmpty(businessCommissionDetails)) {
                //获取关联的执行单并更新商务结算状态为已结算
                List<Long> excuteIds = businessCommissionDetails.stream().map(x -> x.getExcuteId()).collect(Collectors.toList());
                contractExcutionOrderMapper.updateByNoStrategy(Wrappers.<ContractExcutionOrder>lambdaUpdate()
                        .set(ContractExcutionOrder::getBusinessCommissionSettleStatus, 2)
                        .in(ContractExcutionOrder::getId, excuteIds));
            }
            businessCommission.setReleaseTime(new Date());
            //抄送提成单给【钱昱帆】
            // copyBusinessCommission(businessCommission);
        }
        businessCommission.setBusinessStatus(businessStatus);
        businessCommissionMapper.updateById(businessCommission);
    }


    public void invalid(List<BusinessCommissionDetail> businessCommissionDetails) {
        businessCommissionDetails.forEach(x -> {
            x.setIsDelete(NumberCst.ONE);
            x.setIsInvalid(NumberCst.ONE);
        });
        businessCommissionDetailService.updateBatchById(businessCommissionDetails);
        List<BusinessCommissionDetail> list = businessCommissionDetails.stream().filter(x -> Objects.nonNull(x.getTemporaryCode())).collect(Collectors.toList());
        if (list.size() > 0) {
            List<BusinessCommissionDetailTemporary> detailTemporaries = businessCommissionDetailTemporaryMapper.selectList(Wrappers.lambdaQuery(BusinessCommissionDetailTemporary.class)
                    .eq(BusinessCommissionDetailTemporary::getIsDelete, NumberCst.ZERO)
                    .eq(BusinessCommissionDetailTemporary::getTemporaryCode, list.get(0).getTemporaryCode()));
            if (detailTemporaries.size() > 0) {
                detailTemporaries.forEach(x -> {
                    x.setIsDelete(NumberCst.ONE);
                    x.setIsInvalid(NumberCst.ONE);
                });
                businessCommissionDetailTemporaryService.updateBatchById(detailTemporaries);
            }
        }
    }

    /**
     * 抄送商务提成单给【钱昱帆】
     *
     * @param businessCommission 商务提成单
     */
    private void copyBusinessCommission(BusinessCommission businessCommission) {
        SUserVo sendUserVo = aeQuarterlyTableService.getSendUserVo();
        String title = StringUtils.defaultIfBlank(businessCommission.getTitle(), businessCommission.getQuarterCode());
        approvalFlowService.sendBusinessNotify(businessCommission.getTenantId(), businessCommission.getId(), businessCommission.getBusinessCommissionCode(), title,
                ApprovalEnum.BUSINESS_DEFAULT_COMMISSION, false, sendUserVo.getUserId(), sendUserVo.getUsername(), NumberCst.TWO);
    }

    public void setDefaultConfirmed(List<BusinessCommissionDetail> commissionDetails, List<BusinessCommissionDetail> departmentDetails) {
        List<Long> userIds = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(commissionDetails)) {
            Set<Long> commissionIds = commissionDetails.stream().map(BusinessCommissionDetail::getCommissionId).collect(Collectors.toSet());
            userIds.addAll(commissionIds);
        }
        if (CollectionUtil.isNotEmpty(departmentDetails)) {
            Set<Long> departmentHeadIds = departmentDetails.stream().map(BusinessCommissionDetail::getDepartmentHeadId).collect(Collectors.toSet());
            userIds.addAll(departmentHeadIds);
        }
        Map<Long, DepartmentVO> departmentMap = privilegeClient.getDepartmentHeadByUserIds(userIds).getObj();
        List<BusinessCommissionConfirmed> businessCommissionConfirmedList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(commissionDetails)) {
            ArrayList<BusinessCommissionDetail> distinctCommissionDetails = commissionDetails.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(BusinessCommissionDetail::getCommissionId))), ArrayList::new));
            distinctCommissionDetails.forEach(detail -> {
                Integer existCount = businessCommissionConfirmedMapper.selectCount(Wrappers.lambdaQuery(BusinessCommissionConfirmed.class)
                        .eq(BusinessCommissionConfirmed::getBusinessId, detail.getBusinessId())
                        .eq(BusinessCommissionConfirmed::getUserId, detail.getCommissionId())
                        .eq(BusinessCommissionConfirmed::getRole, NumberCst.ZERO)
                        .eq(BusinessCommissionConfirmed::getIsDelete, NumberCst.ZERO));
                if (existCount.equals(NumberCst.ZERO)) {
                    BusinessCommissionConfirmed businessCommissionConfirmed = new BusinessCommissionConfirmed();
                    businessCommissionConfirmed.setBusinessId(detail.getBusinessId());
                    businessCommissionConfirmed.setIsConfirmed(NumberCst.ZERO);
                    if (departmentMap.containsKey(detail.getCommissionId())) {
                        DepartmentVO department = departmentMap.get(detail.getCommissionId());
                        businessCommissionConfirmed.setDepartmentId(department.getDepartmentId());
                        businessCommissionConfirmed.setDepartmentName(department.getDepartmentName());
                    }
                    businessCommissionConfirmed.setRole(NumberCst.ZERO);
                    businessCommissionConfirmed.setUserId(detail.getCommissionId());
                    businessCommissionConfirmed.setUserName(detail.getCommissionName());

                    businessCommissionConfirmedList.add(businessCommissionConfirmed);
                }
            });
        }
        if (CollectionUtil.isNotEmpty(departmentDetails)) {
            ArrayList<BusinessCommissionDetail> distinctDepartmentDetails = departmentDetails.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(BusinessCommissionDetail::getDepartmentHeadId))), ArrayList::new));
            distinctDepartmentDetails.forEach(detail -> {
                Integer existCount = businessCommissionConfirmedMapper.selectCount(Wrappers.lambdaQuery(BusinessCommissionConfirmed.class)
                        .eq(BusinessCommissionConfirmed::getBusinessId, detail.getBusinessId())
                        .eq(BusinessCommissionConfirmed::getUserId, detail.getDepartmentHeadId())
                        .eq(BusinessCommissionConfirmed::getRole, NumberCst.ONE)
                        .eq(BusinessCommissionConfirmed::getIsDelete, NumberCst.ZERO));
                if (existCount.equals(NumberCst.ZERO)) {
                    BusinessCommissionConfirmed businessCommissionConfirmed = new BusinessCommissionConfirmed();
                    businessCommissionConfirmed.setBusinessId(detail.getBusinessId());
                    businessCommissionConfirmed.setIsConfirmed(NumberCst.ZERO);
                    if (departmentMap.containsKey(detail.getDepartmentHeadId())) {
                        DepartmentVO department = departmentMap.get(detail.getDepartmentHeadId());
                        businessCommissionConfirmed.setDepartmentId(department.getDepartmentId());
                        businessCommissionConfirmed.setDepartmentName(department.getDepartmentName());
                    }
                    businessCommissionConfirmed.setRole(NumberCst.ONE);
                    businessCommissionConfirmed.setUserId(detail.getDepartmentHeadId());
                    businessCommissionConfirmed.setUserName(detail.getDepartmentHeadName());
                    businessCommissionConfirmedList.add(businessCommissionConfirmed);
                }
            });
        }
        if (CollectionUtil.isNotEmpty(businessCommissionConfirmedList)) {
            businessCommissionConfirmedMapper.insertBatch(businessCommissionConfirmedList);
        }
    }


    /**
     * 商务弹窗
     *
     * @param page            分页
     * @param businessInfoDTO 查询条件
     * @return {@link BusinessInfo}
     */
    @Override
    public BusinessInfo businessInfo(McnPage<BusinessCommissionDetail> page, BusinessInfoDTO businessInfoDTO) {
        BusinessInfo businessInfo = new BusinessInfo();
        BusinessCommission businessCommission = businessCommissionMapper.selectById(businessInfoDTO.getId());
        if (businessCommission.getBusinessStatus().equals(BusinessCommissionEnum.INVALID.code())) {
            throw new BusinessException(McnErrorCode.BUSINESS_INVALID);
        }
        QueryWrapper<BusinessCommissionDetail> queryWrapper = new QueryWrapper<>();
        businessCommissionQueryWrapper(businessCommission, queryWrapper, businessInfoDTO);
        McnPage<BusinessCommissionDetail> businessCommissionDetailMcnPage = businessCommissionDetailMapper.selectPage(page, queryWrapper);
        PageInfo<PersonalCommission> personalCommissionPageInfo = PageInfo.toPageInfo(page, PersonalCommission.class);
        Integer total = businessCommissionDetailMapper.selectCount(queryWrapper);
        personalCommissionPageInfo.setTotal(total);
        personalCommissionPageInfo.setPageNum(Long.valueOf(businessCommissionDetailMcnPage.getPageNum()).intValue());
        personalCommissionPageInfo.setPageSize(Long.valueOf(businessCommissionDetailMcnPage.getSize()).intValue());
        List<BusinessCommissionDetail> details = businessCommissionDetailMapper.selectList(queryWrapper);
        List<Long> incomeIds = details.stream().map(BusinessCommissionDetail::getIncomeId).distinct().collect(Collectors.toList());
        BigDecimal totalSales = BigDecimal.ZERO;
        if (incomeIds.size() > 0) {
            List<IncomeContract> incomeContracts = incomeContractMapper.selectList(Wrappers.lambdaQuery(IncomeContract.class).in(IncomeContract::getId, incomeIds));
            totalSales = incomeContracts.stream().map(IncomeContract::getBusinessAmount).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_HALF_UP);
        }
        BigDecimal totalAmount = details.stream().filter(x -> Objects.nonNull(x.getPersonalCommission())).map(BusinessCommissionDetail::getPersonalCommission).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_HALF_UP);
        BeanUtils.copyProperties(businessCommission, businessInfo);
        List<Long> ids = Collections.singletonList(businessInfoDTO.getCommissionId());
        List<SUserVo> sUserVos = Objects.requireNonNull(privilegeClient.getDepartmentByUserIds(ids)).getObj();
        if (personalCommissionPageInfo.getTotal() > 0) {
            List<Long> customerIdList = personalCommissionPageInfo.getList().stream().map(PersonalCommission::getCustomerId).distinct().collect(Collectors.toList());
            Map<Long, BaseCustomer> customerMapping = Objects.requireNonNull(baseInfoClient.getMcnCustomerByIds(customerIdList)).getObj();
            personalCommissionPageInfo.getList().forEach(x -> {
                x.setCustomerName(customerMapping.get(x.getCustomerId()).getCustomerNameC());
                IncomeContract incomeContract = incomeContractMapper.selectOne(Wrappers.lambdaQuery(IncomeContract.class).eq(IncomeContract::getContractCode, x.getIncomeCode()));
                x.setApprovalStatus(incomeContract.getApprovalStatus());
                //x.setCommissionSettleStatus(incomeContract.getCommissionSettleStatus());
            });
        }
        sUserVos.forEach(x -> {
            businessInfo.setName(x.getUsername());
            businessInfo.setDepartmentName(x.getDepartmentName());
            businessInfo.setRoleName(x.getRoleName());
        });
        businessInfo.setPersonalCommissionList(personalCommissionPageInfo);
        businessInfo.setTotalSales(totalSales);
        businessInfo.setTotalAmount(totalAmount);
        BusinessCommissionConfirmed commissionConfirmed = businessCommissionConfirmedMapper.selectOne(Wrappers.lambdaQuery(BusinessCommissionConfirmed.class).eq(BusinessCommissionConfirmed::getBusinessId, businessInfoDTO.getId())
                .eq(BusinessCommissionConfirmed::getIsDelete, NumberCst.ZERO)
                .eq(BusinessCommissionConfirmed::getRole, NumberCst.ZERO).eq(BusinessCommissionConfirmed::getUserId, businessInfoDTO.getCommissionId()));
        if (Objects.nonNull(commissionConfirmed)) {
            businessInfo.setIsConfirmed(commissionConfirmed.getIsConfirmed());
        }
        return businessInfo;
    }


    public void businessCommissionQueryWrapper(BusinessCommission businessCommission, QueryWrapper<BusinessCommissionDetail> queryWrapper, BusinessInfoDTO businessInfoDTO) {
        if (businessCommission.getBusinessStatus().equals(BusinessCommissionEnum.INVALID.code())) {
            queryWrapper.lambda().eq(BusinessCommissionDetail::getBusinessId, businessInfoDTO.getId())
                    .eq(BusinessCommissionDetail::getCommissionId, businessInfoDTO.getCommissionId())
                    .eq(BusinessCommissionDetail::getIsInvalid, NumberCst.ONE)
                    .like(StringUtils.isNotBlank(businessInfoDTO.getIncomeCode()), BusinessCommissionDetail::getIncomeCode, businessInfoDTO.getIncomeCode())
                    .eq(Objects.nonNull(businessInfoDTO.getCustomerId()), BusinessCommissionDetail::getCustomerId, businessInfoDTO.getCustomerId());
        } else {
            queryWrapper.lambda().eq(BusinessCommissionDetail::getBusinessId, businessInfoDTO.getId())
                    .eq(BusinessCommissionDetail::getCommissionId, businessInfoDTO.getCommissionId())
                    .eq(BusinessCommissionDetail::getIsDelete, NumberCst.ZERO)
                    .like(StringUtils.isNotBlank(businessInfoDTO.getIncomeCode()), BusinessCommissionDetail::getIncomeCode, businessInfoDTO.getIncomeCode())
                    .eq(Objects.nonNull(businessInfoDTO.getCustomerId()), BusinessCommissionDetail::getCustomerId, businessInfoDTO.getCustomerId());
        }
    }


    /**
     * 商务弹窗导出
     *
     * @param businessInfoDTO 查询条件
     * @param response        {@link HttpServletResponse}
     * @throws Exception 抛异常
     */
    @Override
    public void exportBusinessInfo(BusinessInfoDTO businessInfoDTO, HttpServletResponse response) throws Exception {
        List<BusinessInfoExport> infoList = new ArrayList<>();
        BusinessCommission businessCommission = businessCommissionMapper.selectById(businessInfoDTO.getId());
        QueryWrapper<BusinessCommissionDetail> queryWrapper = new QueryWrapper<>();
        businessCommissionQueryWrapper(businessCommission, queryWrapper, businessInfoDTO);
        List<BusinessCommissionDetail> businessCommissionDetails = businessCommissionDetailMapper.selectList(queryWrapper);
        businessCommissionDetails.forEach(x -> {
            BusinessInfoExport businessInfo = new BusinessInfoExport();
            BeanUtils.copyProperties(x, businessInfo);
            infoList.add(businessInfo);
        });
        List<Long> ids = Collections.singletonList(businessInfoDTO.getCommissionId());
        List<SUserVo> sUserVos = Objects.requireNonNull(privilegeClient.getDepartmentByUserIds(ids)).getObj();
        List<Long> customerIdList = businessCommissionDetails.stream().map(BusinessCommissionDetail::getCustomerId).distinct().collect(Collectors.toList());
        Map<Long, BaseCustomer> customerMapping = Objects.requireNonNull(baseInfoClient.getMcnCustomerByIds(customerIdList)).getObj();
        if (Objects.nonNull(sUserVos) && Objects.nonNull(customerMapping)) {
            List<String> departmentNames = sUserVos.stream().map(SUserVo::getDepartmentName).distinct().collect(Collectors.toList());
            infoList.forEach(x -> {
                x.setDepartmentName(departmentNames.get(0));
                x.setCustomerName(customerMapping.get(x.getCustomerId()).getCustomerNameC());
                IncomeContract incomeContract = incomeContractMapper.selectOne(Wrappers.lambdaQuery(IncomeContract.class).eq(IncomeContract::getContractCode, x.getIncomeCode()));
                x.setApprovalStatus(incomeContract.getApprovalStatus());
                //x.setCommissionSettleStatus(incomeContract.getCommissionSettleStatus());
            });
        }
        String fileName = StringUtils.defaultIfBlank(businessCommission.getTitle(), businessCommission.getQuarterCode() + "商务提成单") + ".xlsx";
        ExcelUtils.exportExcel(infoList, "商务提成", BusinessInfoExport.class, fileName, response);
    }


    /**
     * 商务弹窗 确认提成
     *
     * @param id     提成id
     * @param userId 用户id
     * @param status 状态(1-商务提成，2-部门提成)
     */
    @Override
    public void personalConfirmCommission(Long id, Long userId, Integer status) {
        BusinessCommission businessCommission = businessCommissionMapper.selectById(id);
        if (businessCommission.getBusinessStatus().equals(BusinessCommissionEnum.INVALID.code())) {
            throw new BusinessException(McnErrorCode.BUSINESS_COMMISSION_IS_INVALID);
        }
        List<BusinessCommissionDetail> businessCommissionDetails = new ArrayList<>();
        if (status.equals(NumberCst.ONE)) {
            businessCommissionDetails = businessCommissionDetailMapper.selectList(Wrappers.lambdaQuery(BusinessCommissionDetail.class)
                    .eq(BusinessCommissionDetail::getBusinessId, id)
                    .eq(BusinessCommissionDetail::getCommissionId, userId)
                    .eq(BusinessCommissionDetail::getIsDelete, NumberCst.ZERO));

        }
        if (status.equals(NumberCst.TWO)) {
            businessCommissionDetails = businessCommissionDetailMapper.selectList(Wrappers.lambdaQuery(BusinessCommissionDetail.class)
                    .eq(BusinessCommissionDetail::getBusinessId, id)
                    .eq(BusinessCommissionDetail::getDepartmentHeadId, userId)
                    .eq(BusinessCommissionDetail::getIsDelete, NumberCst.ZERO));
        }
        if (Objects.nonNull(businessCommissionDetails)) {
            businessCommissionDetails.forEach(x -> x.setIsConfirmed(NumberCst.ONE));
            businessCommissionDetailService.updateBatchById(businessCommissionDetails);
        }

        //更新确认信息
        updateConfirmedInfo(id, userId, status);
    }

    private void updateConfirmedInfo(Long id, Long userId, Integer status) {
        LambdaQueryWrapper<BusinessCommissionConfirmed> queryWrapper = Wrappers.lambdaQuery(BusinessCommissionConfirmed.class)
                .eq(BusinessCommissionConfirmed::getBusinessId, id)
                .eq(BusinessCommissionConfirmed::getUserId, userId);
        if (status.equals(NumberCst.ONE)) {
            queryWrapper.eq(BusinessCommissionConfirmed::getRole, NumberCst.ZERO);
        }
        if (status.equals(NumberCst.TWO)) {
            queryWrapper.eq(BusinessCommissionConfirmed::getRole, NumberCst.ONE);
        }
        BusinessCommissionConfirmed businessCommissionConfirmed = businessCommissionConfirmedMapper.selectOne(queryWrapper);
        businessCommissionConfirmed.setIsConfirmed(NumberCst.ONE);
        businessCommissionConfirmed.setConfirmedTime(new Date());
        businessCommissionConfirmedMapper.updateById(businessCommissionConfirmed);
    }

    /**
     * 部门负责人弹窗
     *
     * @param page              分页
     * @param departmentInfoDTO 查询条件
     * @return {@link DepartmentInfo}
     */
    @Override
    public DepartmentInfo departmentInfo(McnPage<BusinessCommissionDetail> page, DepartmentInfoDTO departmentInfoDTO) {
        DepartmentInfo departmentInfo = new DepartmentInfo();
        BusinessCommission businessCommission = businessCommissionMapper.selectById(departmentInfoDTO.getId());
        if (businessCommission.getBusinessStatus().equals(BusinessCommissionEnum.INVALID.code())) {
            throw new BusinessException(McnErrorCode.BUSINESS_INVALID);
        }
        QueryWrapper<BusinessCommissionDetail> queryWrapper = new QueryWrapper<>();
        departmentInfoQueryWrapper(businessCommission, queryWrapper, departmentInfoDTO);
        McnPage<BusinessCommissionDetail> businessCommissionDetailMcnPage = businessCommissionDetailMapper.selectPage(page, queryWrapper);
        PageInfo<BusinessCommissionDetailVO> pageInfo = PageInfo.toPageInfo(page, BusinessCommissionDetailVO.class);
        Integer total = businessCommissionDetailMapper.selectCount(queryWrapper);
        pageInfo.setTotal(total);
        pageInfo.setPageNum(Long.valueOf(businessCommissionDetailMcnPage.getPageNum()).intValue());
        pageInfo.setPageSize(Long.valueOf(businessCommissionDetailMcnPage.getSize()).intValue());
        departmentInfo.setBusinessCommissionDetailVoPageInfo(pageInfo);
        if (pageInfo.getTotal() > 0) {
            List<Long> customerIds = pageInfo.getList().stream().map(BusinessCommissionDetail::getCustomerId).distinct().collect(Collectors.toList());
            Map<Long, BaseCustomer> customerMapping = Objects.requireNonNull(baseInfoClient.getMcnCustomerByIds(customerIds)).getObj();
            if (Objects.nonNull(customerMapping)) {
                pageInfo.getList().forEach(x -> x.setCustomerName(customerMapping.get(x.getCustomerId()).getCustomerNameC()));
            }
            BigDecimal departmentTargetAchievementRate = pageInfo.getList().get(0).getDepartmentTargetAchievementRate();
            departmentInfo.setTargetAchievementRate(departmentTargetAchievementRate);
        }
        List<Long> ids = Collections.singletonList(departmentInfoDTO.getDepartmentHeaderId());
        List<SUserVo> sUserVos = Objects.requireNonNull(privilegeClient.getDepartmentByUserIds(ids)).getObj();
        if (Objects.nonNull(sUserVos)) {
            sUserVos.forEach(x -> {
                departmentInfo.setName(x.getUsername());
                departmentInfo.setDepartmentName(x.getDepartmentName());
                departmentInfo.setRoleName(x.getRoleName());
            });
        }
        List<BusinessCommissionDetail> details = businessCommissionDetailMapper.selectList(queryWrapper);
        BigDecimal totalAmount = details.stream().map(BusinessCommissionDetail::getDepartmentHeadCommission).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_HALF_UP);
        List<Long> incomeIds = details.stream().map(BusinessCommissionDetail::getIncomeId).distinct().collect(Collectors.toList());
        if (incomeIds.size() > 0) {
            List<IncomeContract> incomeContracts = incomeContractMapper.selectList(Wrappers.lambdaQuery(IncomeContract.class).in(IncomeContract::getId, incomeIds));
            BigDecimal totalSales = incomeContracts.stream().map(IncomeContract::getBusinessAmount).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_HALF_UP);
            departmentInfo.setTotalSales(totalSales);
        } else {
            departmentInfo.setTotalSales(new BigDecimal(String.valueOf(BigDecimal.ZERO)));
        }
        departmentInfo.setTotalAmount(totalAmount);
        departmentInfo.setBusinessCommissionCode(businessCommission.getBusinessCommissionCode());
        departmentInfo.setBusinessStatus(businessCommission.getBusinessStatus());
        BusinessCommissionConfirmed commissionConfirmed = businessCommissionConfirmedMapper.selectOne(Wrappers.lambdaQuery(BusinessCommissionConfirmed.class).eq(BusinessCommissionConfirmed::getBusinessId, departmentInfoDTO.getId())
                .eq(BusinessCommissionConfirmed::getIsDelete, NumberCst.ZERO)
                .eq(BusinessCommissionConfirmed::getRole, NumberCst.ONE).eq(BusinessCommissionConfirmed::getUserId, departmentInfoDTO.getDepartmentHeaderId()));
        if (Objects.nonNull(commissionConfirmed)) {
            departmentInfo.setIsConfirmed(commissionConfirmed.getIsConfirmed());
        }
        departmentInfo.setQuarterCode(businessCommission.getQuarterCode());
        departmentInfo.setTitle(businessCommission.getTitle());
        return departmentInfo;
    }


    public void departmentInfoQueryWrapper(BusinessCommission businessCommission, QueryWrapper<BusinessCommissionDetail> queryWrapper, DepartmentInfoDTO departmentInfoDTO) {
        if (businessCommission.getBusinessStatus().equals(BusinessCommissionEnum.INVALID.code())) {
            queryWrapper.lambda().eq(BusinessCommissionDetail::getBusinessId, departmentInfoDTO.getId())
                    .eq(BusinessCommissionDetail::getDepartmentHeadId, departmentInfoDTO.getDepartmentHeaderId())
                    .eq(BusinessCommissionDetail::getIsInvalid, NumberCst.ONE)
                    .like(StringUtils.isNotBlank(departmentInfoDTO.getIncomeCode()), BusinessCommissionDetail::getIncomeCode, departmentInfoDTO.getIncomeCode())
                    .eq(Objects.nonNull(departmentInfoDTO.getCustomerId()), BusinessCommissionDetail::getCustomerId, departmentInfoDTO.getCustomerId()
                    );
        } else {
            queryWrapper.lambda().eq(BusinessCommissionDetail::getBusinessId, departmentInfoDTO.getId())
                    .eq(BusinessCommissionDetail::getDepartmentHeadId, departmentInfoDTO.getDepartmentHeaderId())
                    .eq(BusinessCommissionDetail::getIsDelete, NumberCst.ZERO)
                    .like(StringUtils.isNotBlank(departmentInfoDTO.getIncomeCode()), BusinessCommissionDetail::getIncomeCode, departmentInfoDTO.getIncomeCode())
                    .eq(Objects.nonNull(departmentInfoDTO.getCustomerId()), BusinessCommissionDetail::getCustomerId, departmentInfoDTO.getCustomerId());
        }
    }


    /**
     * 部门负责人弹窗导出
     *
     * @param departmentInfoDTO 查询条件
     * @param response          {@link HttpServletResponse}
     * @throws Exception 抛异常
     */
    @Override
    public void exportDepartInfo(DepartmentInfoDTO departmentInfoDTO, HttpServletResponse response) throws Exception {
        BusinessCommission businessCommission = businessCommissionMapper.selectById(departmentInfoDTO.getId());
        QueryWrapper<BusinessCommissionDetail> queryWrapper = new QueryWrapper<>();
        departmentInfoQueryWrapper(businessCommission, queryWrapper, departmentInfoDTO);
        List<BusinessCommissionDetail> businessCommissionDetails = businessCommissionDetailMapper.selectList(queryWrapper);
        List<Long> customerIds = businessCommissionDetails.stream().map(BusinessCommissionDetail::getCustomerId).distinct().collect(Collectors.toList());
        Map<Long, BaseCustomer> customerMapping = Objects.requireNonNull(baseInfoClient.getMcnCustomerByIds(customerIds)).getObj();
        List<BusinessDepartInfoExportVO> list = new ArrayList<>();
        businessCommissionDetails.forEach(x -> {
            BusinessDepartInfoExportVO detailVO = new BusinessDepartInfoExportVO();
            BeanUtils.copyProperties(x, detailVO);
            list.add(detailVO);
        });
        if (Objects.nonNull(customerMapping)) {
            list.forEach(x -> x.setCustomerName(customerMapping.get(x.getCustomerId()).getCustomerNameC()));
        }
        String fileName = StringUtils.defaultIfBlank(businessCommission.getTitle(), businessCommission.getQuarterCode() + "商务提成单") + ".xlsx";
        ExcelUtils.exportExcel(list, "商务提成", BusinessDepartInfoExportVO.class, fileName, response);
    }

    @Override
    public BusinessCommissionInfoVO getShortDetail(Long id) {
        BusinessCommission businessCommission = baseMapper.selectById(id);
        BusinessCommissionInfoVO businessCommissionInfoVO = new BusinessCommissionInfoVO();
        BeanUtils.copyProperties(businessCommission, businessCommissionInfoVO);
        return businessCommissionInfoVO;
    }

    @Override
    public PageInfo<BusinessCommissionDetail> getDetailPage(BusinessCommissionDetailPageDTO dto) {
        Page<BusinessCommissionDetail> page = businessCommissionDetailMapper.selectPage(
                new Page<>(dto.getPageNum(), dto.getPageSize()),
                Wrappers.lambdaQuery(BusinessCommissionDetail.class)
                        .eq(BusinessCommissionDetail::getBusinessId, dto.getBusinessId())
                        .eq(BusinessCommissionDetail::getIsDelete, NumberCst.ZERO));
        return PageInfo.toPageInfo(page);
    }

    @Override
    public BusinessConfirmationDetails getCheckDetailPage(BusinessCheckDetailPageDTO dto) {
        Map<Long, BigDecimal> departmentHeaderMap = new HashMap<>(16);
        Map<Long, BigDecimal> commissionMap = new HashMap<>(16);
        BusinessCommission businessCommission = businessCommissionMapper.selectById(dto.getBusinessId());
        QueryWrapper<BusinessCommissionDetail> queryWrapper = new QueryWrapper<>();
        List<BusinessCommissionDetail> details = getBusinessDetail(businessCommission, queryWrapper);
        List<Long> commissionIdList = details.stream().map(BusinessCommissionDetail::getCommissionId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        List<Long> departmentHeadIdList = details.stream().map(BusinessCommissionDetail::getDepartmentHeadId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        BusinessConfirmationDetails businessConfirmationDetails = new BusinessConfirmationDetails();
        BeanUtils.copyProperties(businessCommission, businessConfirmationDetails);
        McnPage<BusinessCommissionConfirmed> mcnPage = new McnPage<>();
        mcnPage.setPageNum(dto.getPageNum()).setPageSize(dto.getPageSize());
        Page<BusinessCommissionConfirmed> page = new Page<>();
        if (commissionIdList.size() > 0) {
            page = businessCommissionConfirmedMapper.getConfirmedList(mcnPage, dto.getBusinessId(), commissionIdList, departmentHeadIdList);
        }
        List<BusinessCommissionConfirmVO> list = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(page.getRecords())) {
            page.getRecords().forEach(item -> {
                BusinessCommissionConfirmVO confirmVO = new BusinessCommissionConfirmVO();
                BeanUtils.copyProperties(item, confirmVO);
                list.add(confirmVO);
            });
        }
        List<Long> commissionIds = list.stream().filter(x -> x.getRole() == 0).map(BusinessCommissionConfirmVO::getUserId).collect(Collectors.toList());
        List<Long> departmentHeaderIds = list.stream().filter(x -> x.getRole() == 1).map(BusinessCommissionConfirmVO::getUserId).collect(Collectors.toList());
        if (commissionIds.size() > 0) {
            List<BusinessCommissionDetail> commissionDetails = businessCommissionDetailMapper.getPersonalCommissions(dto.getBusinessId(), commissionIds, businessCommission.getBusinessStatus());
            commissionMap = commissionDetails.stream().collect(Collectors.toMap(BusinessCommissionDetail::getCommissionId, BusinessCommissionDetail::getPersonalCommission));
        }
        if (departmentHeaderIds.size() > 0) {
            List<BusinessCommissionDetail> departmentCommissions = businessCommissionDetailMapper.getDepartmentCommissions(dto.getBusinessId(), departmentHeaderIds, businessCommission.getBusinessStatus());
            departmentHeaderMap = departmentCommissions.stream().collect(Collectors.toMap(BusinessCommissionDetail::getDepartmentHeadId, BusinessCommissionDetail::getDepartmentHeadCommission));
        }
        Map<Long, BigDecimal> finalDepartmentHeaderMap = departmentHeaderMap;
        Map<Long, BigDecimal> finalCommissionMap = commissionMap;
        list.forEach(x -> {
            if (x.getRole() == 0) {
                if (finalCommissionMap.size() > 0 && Objects.nonNull(finalCommissionMap.get(x.getUserId()))) {
                    x.setRoyaltyAmount(finalCommissionMap.get(x.getUserId()));
                } else {
                    x.setRoyaltyAmount(BigDecimal.ZERO);
                }
            }
            if (x.getRole() == 1) {
                if (finalDepartmentHeaderMap.size() > 0 && Objects.nonNull(finalDepartmentHeaderMap.get(x.getUserId()))) {
                    x.setRoyaltyAmount(finalDepartmentHeaderMap.get(x.getUserId()));
                } else {
                    x.setRoyaltyAmount(BigDecimal.ZERO);
                }
            }
        });
        Page<BusinessCommissionConfirmVO> iPage = iPage(page, list);
        businessConfirmationDetails.setConfirmList(PageInfo.toPageInfo(iPage, BusinessCommissionConfirmVO.class));
        return businessConfirmationDetails;
    }


    private List<BusinessCommissionDetail> getBusinessDetail(BusinessCommission businessCommission, QueryWrapper<BusinessCommissionDetail> queryWrapper) {
        if (businessCommission.getBusinessStatus().equals(BusinessCommissionEnum.INVALID.code())) {
            queryWrapper.lambda().eq(BusinessCommissionDetail::getBusinessId, businessCommission.getId())
                    .eq(BusinessCommissionDetail::getIsInvalid, NumberCst.ONE);
        } else {
            queryWrapper.lambda().eq(BusinessCommissionDetail::getBusinessId, businessCommission.getId())
                    .eq(BusinessCommissionDetail::getIsDelete, NumberCst.ZERO);
        }
        return businessCommissionDetailMapper.selectList(queryWrapper);
    }


    public Page<BusinessCommissionConfirmVO> iPage(Page<BusinessCommissionConfirmed> page, List<BusinessCommissionConfirmVO> list) {
        Page<BusinessCommissionConfirmVO> iPage = new Page<>();
        iPage.setRecords(list);
        iPage.setTotal(page.getTotal());
        iPage.setSize(page.getSize());
        iPage.setPages(page.getPages());
        return iPage;
    }

    @Override
    public void sendBusinessCommission(Long id) {
        BusinessCommissionConfirmed businessCommissionConfirmed = businessCommissionConfirmedMapper.selectById(id);
        verifyUsersCommission(businessCommissionConfirmed);
        final BusinessCommission businessCommission = businessCommissionMapper.selectById(businessCommissionConfirmed.getBusinessId());
        String title = StringUtils.defaultIfBlank(businessCommission.getTitle(), businessCommission.getQuarterCode());
        if (businessCommissionConfirmed.getRole().equals(NumberCst.ZERO)) {
            approvalFlowService.sendBusinessNotify(businessCommission.getTenantId(), businessCommissionConfirmed.getBusinessId(), businessCommission.getBusinessCommissionCode(), title,
                    ApprovalEnum.BUSINESS_COMMISSION, true, businessCommissionConfirmed.getUserId(), businessCommissionConfirmed.getUserName(), NumberCst.ONE);
        }
        if (businessCommissionConfirmed.getRole().equals(NumberCst.ONE)) {
            approvalFlowService.sendBusinessNotify(businessCommission.getTenantId(), businessCommissionConfirmed.getBusinessId(), businessCommission.getBusinessCommissionCode(), title,
                    ApprovalEnum.BUSINESS_DEPARTMENT, true, businessCommissionConfirmed.getUserId(), businessCommissionConfirmed.getUserName(), NumberCst.TWO);
        }
        businessCommissionConfirmed.setIsConfirmed(NumberCst.ZERO);
        businessCommissionConfirmed.setConfirmedTime(null);
        businessCommissionConfirmedMapper.updateById(businessCommissionConfirmed);
    }

    private void verifyUsersCommission(BusinessCommissionConfirmed businessCommissionConfirmed) {
        Integer role = businessCommissionConfirmed.getRole();
        if (NumberCst.ZERO.equals(role)) {
            BusinessAssert.isTrue(businessCommissionDetailMapper.exist(Wrappers.lambdaQuery(BusinessCommissionDetail.class)
                    .eq(BusinessCommissionDetail::getBusinessId, businessCommissionConfirmed.getBusinessId())
                    .eq(BusinessCommissionDetail::getCommissionId, businessCommissionConfirmed.getUserId())
                    .eq(BusinessCommissionDetail::getIsDelete, NumberCst.ZERO)), McnErrorCode.USERS_BUSINESS_COMMISSION_NOT_EXIST);
        }
        if (NumberCst.ONE.equals(role)) {
            BusinessAssert.isTrue(businessCommissionDetailMapper.exist(Wrappers.lambdaQuery(BusinessCommissionDetail.class)
                    .eq(BusinessCommissionDetail::getBusinessId, businessCommissionConfirmed.getBusinessId())
                    .eq(BusinessCommissionDetail::getDepartmentHeadId, businessCommissionConfirmed.getUserId())
                    .eq(BusinessCommissionDetail::getIsDelete, NumberCst.ZERO)), McnErrorCode.USERS_BUSINESS_COMMISSION_NOT_EXIST);
        }
    }

    @Override
    public void exportDetailPage(BusinessCommissionDetailPageDTO businessCommissionDetailPageDTO, HttpServletResponse response) {
        BusinessCommission businessCommission = businessCommissionMapper.selectById(businessCommissionDetailPageDTO.getBusinessId());
        List<BusinessCommissionDetailExportVO> detailExportList = new ArrayList<>();
        List<BusinessCommissionDetail> businessCommissionDetails = businessCommissionDetailMapper.selectList(Wrappers.lambdaQuery(BusinessCommissionDetail.class)
                .eq(BusinessCommissionDetail::getBusinessId, businessCommissionDetailPageDTO.getBusinessId())
                .eq(BusinessCommissionDetail::getIsDelete, NumberCst.ZERO));
        if (CollectionUtil.isNotEmpty(businessCommissionDetails)) {
            for (BusinessCommissionDetail businessCommissionDetail : businessCommissionDetails) {
                BusinessCommissionDetailExportVO commissionDetailExportVO = new BusinessCommissionDetailExportVO();
                BeanUtils.copyProperties(businessCommissionDetail, commissionDetailExportVO);
                detailExportList.add(commissionDetailExportVO);
            }
        }
        String fileName = StringUtils.defaultIfBlank(businessCommission.getTitle(), businessCommission.getQuarterCode() + "商务提成单") + ".xlsx";
        try {
            ExcelUtils.exportExcel(detailExportList, "商务提成", BusinessInfoExport.class, fileName, response);
        } catch (Exception e) {
            throw new com.chenfan.common.exception.BusinessException(McnErrorCode.EXPORT_EXCEPTION);
        }
    }


    /**
     * 修改提成单
     *
     * @param dto {@link BusinessCommissionAddDTO}
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateData(BusinessCommissionAddDTO dto) {
        BusinessAssert.notNull(dto.getId(), McnErrorCode.PARAM_ERROR, "提成单ID不能为空");
        BusinessAssert.notBlank(dto.getTitle(), McnErrorCode.PARAM_ERROR, "提成单标题不能为空");
        BusinessCommission entity = businessCommissionMapper.selectById(dto.getId());
        BusinessAssert.notNull(entity, McnErrorCode.DATA_NOT_FOUND);
        BusinessAssert.isTrue(!BusinessCommissionEnum.issued(entity.getBusinessStatus()), McnErrorCode.PARAM_ERROR, "提成单已发放不允许修改！");
        BusinessAssert.isTrue(this.baseMapper.notExist(Wrappers.lambdaQuery(BusinessCommission.class).eq(BusinessCommission::getTitle, dto.getTitle())
                        .ne(BusinessCommission::getId, entity.getId()).ne(BusinessCommission::getBusinessStatus, BusinessCommissionEnum.INVALID.code()))
                , McnErrorCode.BUSINESS_COMMISSION_TITLE_REPEATED);
        BusinessCommission businessCommission = new BusinessCommission();
        businessCommission.setId(entity.getId());
        businessCommission.setTitle(dto.getTitle());
        businessCommission.setRemark(dto.getRemark());
        return businessCommissionMapper.updateById(businessCommission) > 0;
    }


    /**
     * 批量删除(编辑)
     *
     * @param ids {@link List<Long>}
     * @return {@link Boolean}
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean batchDeleteDetail(List<Long> ids) {
        List<BusinessCommissionDetail> oldList = businessCommissionDetailMapper.selectList(Wrappers.lambdaQuery(BusinessCommissionDetail.class)
                .in(BusinessCommissionDetail::getId, ids).eq(BusinessCommissionDetail::getIsDelete, NumberCst.ZERO));
        BusinessAssert.notEmpty(oldList, McnErrorCode.DATA_NOT_FOUND);
        List<Long> oldExcuteIds = oldList.stream().map(x -> x.getExcuteId()).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        oldList.forEach(x -> x.setIsDelete(NumberCst.ONE));
        boolean delete = businessCommissionDetailService.updateBatchById(oldList);
        //获取关联的执行单并更新商务结算状态为未结算
        String temporaryCode = oldList.stream().map(BusinessCommissionDetail::getTemporaryCode).filter(Objects::nonNull).findFirst().orElse(null);
        List<Long> businessIds = oldList.stream().map(BusinessCommissionDetail::getBusinessId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        List<BusinessCommissionDetail> newList = businessCommissionDetailMapper.selectList(Wrappers.lambdaQuery(BusinessCommissionDetail.class)
                .in(BusinessCommissionDetail::getBusinessId, businessIds).eq(BusinessCommissionDetail::getIsDelete, NumberCst.ZERO));
        List<Long> newExcuteIds = CommonUtil.defaultList(newList).stream().map(x -> x.getExcuteId()).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        List<Long> deleteExcuteIds = oldExcuteIds.stream().filter(e -> !newExcuteIds.contains(e)).collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(deleteExcuteIds)) {
            contractExcutionOrderMapper.updateByNoStrategy(Wrappers.<ContractExcutionOrder>lambdaUpdate()
                    .set(ContractExcutionOrder::getBusinessCommissionSettleStatus, NumberCst.ZERO)
                    .in(ContractExcutionOrder::getId, deleteExcuteIds)
                    .eq(ContractExcutionOrder::getBusinessCommissionSettleStatus, NumberCst.ONE));
        }
        //删除临时表数据
        if (StringUtils.isNotBlank(temporaryCode)) {
            List<BusinessCommissionDetailTemporary> temporaries = businessCommissionDetailTemporaryMapper.selectList(Wrappers.lambdaQuery(BusinessCommissionDetailTemporary.class)
                    .eq(BusinessCommissionDetailTemporary::getTemporaryCode, temporaryCode)
                    .eq(BusinessCommissionDetailTemporary::getIsDelete, NumberCst.ZERO));
            if (CollectionUtils.isNotEmpty(temporaries)) {
                temporaries.forEach(x -> x.setIsDelete(NumberCst.ONE));
                businessCommissionDetailTemporaryService.updateBatchById(temporaries);
            }
        }
        return delete;
    }


    /**
     * 编辑列表
     *
     * @param dto 传参
     * @return {@link Integer}
     */
    @SneakyThrows
    @Override
    public Object editDetail(BusinessCommissionUpdateDTO dto) {
        List<Long> commissionIds = new ArrayList<>(Collections.singletonList(dto.getCommissionId()));
        commissionIds.add(dto.getDepartmentHeadId());
        List<SUser> sUsers = Objects.requireNonNull(privilegeClient.getUserByIds(commissionIds)).getObj();
        Map<Long, SUser> sUserMap = sUsers.stream().collect(Collectors.toMap(SUser::getUserId, sUser -> sUser));
        BusinessCommissionDetail detail = businessCommissionDetailMapper.selectById(dto.getId());
        detail.setGeneralPoints(BigDecimal.ZERO);
        detail.setCommissionId(dto.getCommissionId());
        detail.setCommissionName(dto.getCommissionName());
        detail.setDepartmentHeadId(dto.getDepartmentHeadId());
        detail.setDepartmentHeadName(dto.getDepartmentHeadName());
        detail.setDepartmentHeadCommissionPoint(BigDecimal.ZERO);
        detail.setTargetAchievementRate(BigDecimal.ZERO);
        // detail.setPersonalCommission(dto.getPersonalCommission());
        // detail.setDepartmentHeadCommission(dto.getDepartmentHeadCommission());
        if (Objects.nonNull(sUserMap.get(dto.getCommissionId()))) {
            detail.setJobNumber(sUserMap.get(dto.getCommissionId()).getJobNumber());
        }
        if (Objects.nonNull(sUserMap.get(dto.getDepartmentHeadId()))) {
            detail.setDepartmentJobNumber(sUserMap.get(dto.getDepartmentHeadId()).getJobNumber());
        }
        detail.setRemark(dto.getRemark());
        int update = businessCommissionDetailMapper.updateById(detail);
        List<BusinessCommissionDetail> businessCommissionDetails = Collections.singletonList(detail);
        setDefaultConfirmed(businessCommissionDetails, businessCommissionDetails);
        return update;
    }

    /**
     * 保存商务提成明细
     *
     * @param businessCommission {@link BusinessCommission}
     */
    @Override
    public void saveBusinessDetails(BusinessCommission businessCommission, List<BusinessCommissionDetail> detailList) {
        businessCommissionDetailMapper.insertBatch(detailList);
        // 新增部分需要初始化确认信息
        List<BusinessCommissionDetail> commissionDetails = detailList.stream().filter(CommonUtil.distinctByKey(BusinessCommissionDetail::getCommissionId)).collect(Collectors.toList());
        List<BusinessCommissionDetail> departmentDetails = detailList.stream().filter(x -> Objects.nonNull(x.getDepartmentHeadId())).filter(CommonUtil.distinctByKey(BusinessCommissionDetail::getDepartmentHeadId)).collect(Collectors.toList());
        this.setDefaultConfirmed(commissionDetails, departmentDetails);
    }

    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String importBatchSave(BusinessCommission businessCommission, List<BusinessCommissionBatchSaveDTO> inputList) {
        List<BusinessCommissionBatchSaveOutDTO> outputList = new ArrayList<>();
        List<String> incomeCodes = inputList.stream().filter(e -> StringUtils.isNotBlank(e.getContractCode())).map(BusinessCommissionBatchSaveDTO::getContractCode).distinct().collect(Collectors.toList());
        Map<String, IncomeContract> incomeContractMap = null;
        if (CollectionUtils.isNotEmpty(incomeCodes)) {
            List<IncomeContract> incomeContractList = incomeContractMapper.selectList(Wrappers.lambdaQuery(IncomeContract.class)
                    .in(IncomeContract::getContractCode, incomeCodes)
                    .eq(IncomeContract::getIsDelete, NumberCst.ZERO).ne(IncomeContract::getApprovalStatus, ApprovalStatusEnum.INVALID.code()));
            if (CollectionUtils.isNotEmpty(incomeContractList)) {
                incomeContractMap = incomeContractList.stream().collect(Collectors.toMap(IncomeContract::getContractCode, e -> e));
            }
        }
        List<String> userNameList = new NoRepeatableArrayList<>();
        for (BusinessCommissionBatchSaveDTO input : inputList) {
            userNameList.add(input.getCommissionName());
            userNameList.add(input.getDepartmentHeadName());
        }
        Map<String, SUserVo> userMap = null;
        if (CollectionUtils.isNotEmpty(userNameList)) {
            userMap = Objects.requireNonNull(privilegeClient.getUserIdsByName(userNameList)).getObj();
        }
        List<BusinessCommissionBatchSaveDTO> addInputList = new ArrayList<>();
        List<BusinessCommissionDetail> modifyList = new ArrayList<>();
        AtomicBoolean unpassed = new AtomicBoolean(false);
        for (BusinessCommissionBatchSaveDTO input : inputList) {
            boolean allParamEmpty = StringUtils.isBlank(input.getContractCode())
                    && input.getGeneralPoints() == null
                    && input.getTargetAchievementRate() == null
                    && StringUtils.isBlank(input.getCommissionName())
                    && input.getPersonalCommission() == null
                    && StringUtils.isBlank(input.getDepartmentHeadName())
                    && input.getDepartmentHeadCommissionPoint() == null
                    && input.getDepartmentHeadCommission() == null;
            if (allParamEmpty) {
                continue;
            }
            BusinessCommissionBatchSaveOutDTO output = new BusinessCommissionBatchSaveOutDTO();
            BeanUtils.copyProperties(input, output);
            outputList.add(output);
            String failedReason = verifyExcelImportAdd(input, incomeContractMap, userMap);
            if (StringUtils.isNotBlank(failedReason)) {
                output.setFailedReason(failedReason);
                unpassed.compareAndSet(false, true);
                continue;
            }
            List<BusinessCommissionDetail> dataList = businessCommissionDetailMapper.selectList(Wrappers.lambdaQuery(BusinessCommissionDetail.class)
                    .eq(BusinessCommissionDetail::getBusinessId, businessCommission.getId())
                    .eq(BusinessCommissionDetail::getIncomeCode, input.getContractCode())
                    .eq(BusinessCommissionDetail::getCommissionName, input.getCommissionName())
                    .eq(BusinessCommissionDetail::getIsDelete, NumberCst.ZERO));
            IncomeContract incomeContract = incomeContractMap.get(input.getContractCode());
            //int settleStatus = ObjectUtils.defaultIfNull(incomeContract.getCommissionSettleStatus(), -1).intValue();
            refactor(userMap, addInputList, modifyList, unpassed, input, output, dataList, -1);
        }
        if (unpassed.get()) {
            /**
             * 上传错误Excel
             * 将包含错误原因的输出内容存在redis，方便用户下载错误原因是将其导出成Excel
             */
            String fileId = ImportExcelEnum.BUSINESS_COMMISSION_BATCH_SAVE.getFileId();
            redisTemplate.opsForValue().set(McnConstant.CACHE_PRIFIX + fileId, JSONObject.toJSONString(outputList), 30, TimeUnit.DAYS);
            return fileId;
        } else {
            if (CollectionUtils.isNotEmpty(modifyList)) {
                for (BusinessCommissionDetail detail : modifyList) {
                    businessCommissionDetailMapper.updateById(detail);
                }
            }
            refactor(businessCommission, incomeCodes, userMap, addInputList);
        }
        return "";
    }

    private void refactor(BusinessCommission businessCommission, List<String> incomeCodes, Map<String, SUserVo> userMap, List<BusinessCommissionBatchSaveDTO> addInputList) {
        if (CollectionUtils.isNotEmpty(addInputList)) {
            List<String> addIncomeCodes = addInputList.stream().filter(e -> StringUtils.isNotBlank(e.getContractCode())).map(BusinessCommissionBatchSaveDTO::getContractCode).distinct().collect(Collectors.toList());
            List<QuarterIncomeContractVO> qiList = incomeContractMapper.selectQuarterIncomeContracts(addIncomeCodes);
            Map<String, QuarterIncomeContractVO> qiMap = qiList.stream().collect(Collectors.toMap(QuarterIncomeContractVO::getContractCode, e -> e));
            List<BusinessCommissionDetail> detailList = new ArrayList<>(addInputList.size());
            for (BusinessCommissionBatchSaveDTO addInput : addInputList) {
                BusinessCommissionDetail detail = new BusinessCommissionDetail();
                QuarterIncomeContractVO quarterIncomeContract = qiMap.get(addInput.getContractCode());
                detail.setBusinessId(businessCommission.getId());
                detail.setIncomeId(quarterIncomeContract.getId());
                detail.setIncomeCode(quarterIncomeContract.getContractCode());
                detail.setSignDate(quarterIncomeContract.getSignDate());
                detail.setBusinessAmount(quarterIncomeContract.getBusinessAmount());
                detail.setCustomerFirstOrder(quarterIncomeContract.getCustomerFirstOrder().booleanValue() ? NumberCst.ONE : NumberCst.ZERO);
                detail.setPayBackStatus(quarterIncomeContract.getPayBackStatus());
                detail.setCustomerId(quarterIncomeContract.getCustomerId());
                detail.setTargetAchievementRate(addInput.getTargetAchievementRate());
                SUserVo personalUser = userMap.get(addInput.getCommissionName());
                detail.setCommissionId(personalUser.getUserId());
                detail.setCommissionName(addInput.getCommissionName());
                detail.setJobNumber(personalUser.getJobNumber());
                detail.setGeneralPoints(addInput.getGeneralPoints());
                detail.setPersonalCommission(addInput.getPersonalCommission());
                SUserVo headUser = userMap.get(addInput.getDepartmentHeadName());
                detail.setDepartmentHeadId(headUser.getUserId());
                detail.setDepartmentHeadName(addInput.getDepartmentHeadName());
                detail.setDepartmentJobNumber(headUser.getJobNumber());
                detail.setDepartmentHeadCommissionPoint(addInput.getDepartmentHeadCommissionPoint());
                detail.setDepartmentHeadCommission(addInput.getDepartmentHeadCommission());
                detail.setRemark(addInput.getRemark());
                detailList.add(detail);
            }
            List<Long> customerIds = detailList.stream().map(BusinessCommissionDetail::getCustomerId).distinct().collect(Collectors.toList());
            List<Long> commissionIds = detailList.stream().map(BusinessCommissionDetail::getCommissionId).distinct().collect(Collectors.toList());
            List<Long> departmentIds = qiList.stream().map(QuarterIncomeContractVO::getDepartmentId).distinct().collect(Collectors.toList());
            Map<Long, BaseCustomer> customerMap = Objects.requireNonNull(baseInfoClient.getMcnCustomerByIds(customerIds)).getObj();
            List<String> quarterCodeList = qiList.stream().map(QuarterIncomeContractVO::getQuarterCode).distinct().collect(Collectors.toList());
            List<CustomerTarget> customerTargets = customerTargetMapper.selectList(Wrappers.lambdaQuery(CustomerTarget.class).eq(CustomerTarget::getIsDelete, false)
                    .in(CustomerTarget::getQuarterCode, quarterCodeList).in(CustomerTarget::getTargetCustomerId, customerIds));
            List<DepartmentTarget> departmentTargets = departmentTargetMapper.selectList(Wrappers.lambdaQuery(DepartmentTarget.class).eq(DepartmentTarget::getIsDelete, false)
                    .eq(DepartmentTarget::getQuarterCode, businessCommission.getQuarterCode()).in(DepartmentTarget::getDepartmentId, departmentIds));
            Map<Long, DepartmentVO> departmentVoMap = Objects.requireNonNull(privilegeClient.getDepartmentHeadByUserIds(commissionIds)).getObj();
            BusinessCommissionRuleContext context = new BusinessCommissionRuleContext(businessCommission.getBusinessCommissionCode(), customerMap, departmentVoMap, null, departmentTargets, customerTargets);
            this.extendBusinessCommissionDetail(detailList, qiMap, userMap, context);
            this.saveBusinessDetails(businessCommission, detailList);
        }
    }

    private void refactor(Map<String, SUserVo> userMap, List<BusinessCommissionBatchSaveDTO> addInputList, List<BusinessCommissionDetail> modifyList, AtomicBoolean unpassed, BusinessCommissionBatchSaveDTO input, BusinessCommissionBatchSaveOutDTO output, List<BusinessCommissionDetail> dataList, int settleStatus) {
        if (CollectionUtils.isNotEmpty(dataList)) {
            if (CommonSettleStatusEnum.IN_SETTLEMENT.code() == settleStatus) {
                //匹配上&结算中
                for (BusinessCommissionDetail data : dataList) {
                    BusinessCommissionDetail detail = new BusinessCommissionDetail();
                    detail.setId(data.getId());
                    detail.setGeneralPoints(input.getGeneralPoints());
                    //客户目标达成率，重点客户-允许Excel修改 非重点-100%
                    detail.setTargetAchievementRate(NumberCst.ZERO.equals(data.getKeyCustomers()) ? input.getTargetAchievementRate() : BigDecimal.ONE);
                    detail.setPersonalCommission(input.getPersonalCommission());
                    detail.setDepartmentHeadCommissionPoint(input.getDepartmentHeadCommissionPoint());
                    detail.setDepartmentHeadCommission(input.getDepartmentHeadCommission());
                    SUserVo header = userMap.get(input.getDepartmentHeadName());
                    if (header != null) {
                        detail.setDepartmentHeadId(header.getUserId());
                        detail.setDepartmentHeadName(header.getUsername());
                        detail.setDepartmentJobNumber(header.getJobNumber());
                    }
                    detail.setRemark(input.getRemark());
                    modifyList.add(detail);
                }
            } else {
                output.setFailedReason("合同的提成发放状态须是【结算中】");
                unpassed.compareAndSet(false, true);
            }

        } else {
            if (CommonSettleStatusEnum.UNSETTLED.code() == settleStatus) {
                //匹配不上&未结算 - 新增
                addInputList.add(input);
            } else {
                output.setFailedReason("合同的提成发放状态须是【未结算】");
                unpassed.compareAndSet(false, true);
            }
        }
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public String importBatchDelete(BusinessCommission businessCommission, List<BusinessCommissionBatchDeleteDTO> inputList) {
        List<String> contractCodes = inputList.stream().filter(t -> StringUtils.isNotBlank(t.getIncomeContractCode()))
                .map(BusinessCommissionBatchDeleteDTO::getIncomeContractCode).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(contractCodes)) {
            throw new BusinessException(McnErrorCode.IMPORT_CONTENT_EMPTY);
        }
        List<BusinessCommissionBatchDeleteOutDTO> outList = new ArrayList<>(inputList.size());
        List<BusinessCommissionDetail> dataList = businessCommissionDetailMapper.selectList(Wrappers.lambdaQuery(BusinessCommissionDetail.class)
                .eq(BusinessCommissionDetail::getBusinessId, businessCommission.getId())
                .in(BusinessCommissionDetail::getIncomeCode, contractCodes)
                .eq(BusinessCommissionDetail::getIsDelete, NumberCst.ZERO));
        AtomicBoolean unpassed = new AtomicBoolean(false);
        if (CollectionUtils.isEmpty(dataList)) {
            inputList.forEach(item -> {
                BusinessCommissionBatchDeleteOutDTO outDTO = new BusinessCommissionBatchDeleteOutDTO();
                outDTO.setIncomeContractCode(item.getIncomeContractCode());
                outDTO.setFailedReason(StringUtils.isBlank(item.getIncomeContractCode()) ? "合同编号必填" : "合同编号错误");
                outList.add(outDTO);
                unpassed.compareAndSet(false, true);
            });
        } else {
            List<String> existContractCodes = dataList.stream().map(BusinessCommissionDetail::getIncomeCode).distinct().collect(Collectors.toList());
            inputList.forEach(item -> {
                BusinessCommissionBatchDeleteOutDTO outDTO = new BusinessCommissionBatchDeleteOutDTO();
                outDTO.setIncomeContractCode(item.getIncomeContractCode());
                if (StringUtils.isBlank(item.getIncomeContractCode())) {
                    outDTO.setFailedReason("合同编号必填");
                    unpassed.compareAndSet(false, true);
                } else if (!existContractCodes.contains(item.getIncomeContractCode())) {
                    outDTO.setFailedReason("合同编号错误");
                    unpassed.compareAndSet(false, true);
                }
                outList.add(outDTO);
            });
        }
        if (unpassed.get()) {
            String fileId = ImportExcelEnum.BUSINESS_COMMISSION_BATCH_DELETE.getFileId();
            redisTemplate.opsForValue().set(McnConstant.CACHE_PRIFIX + fileId, JSONObject.toJSONString(outList), 30, TimeUnit.DAYS);
            return fileId;
        }
        List<Long> detailIdList = dataList.stream().map(BusinessCommissionDetail::getId).collect(Collectors.toList());
        this.batchDeleteDetail(detailIdList);
        return "";
    }

    @Override
    public void excelDownload(HttpServletResponse response, String fileId) {
        ImportExcelEnum importExcelEnum = ImportExcelEnum.toEnum(fileId);
        BusinessAssert.notNull(importExcelEnum, McnErrorCode.EXPORT_FILE_ID_ILLEGAL);
        try {
            String title = "";
            switch (importExcelEnum) {
                case BUSINESS_COMMISSION_BATCH_SAVE:
                    title = "商务提成-批量导入失败原因";
                    List<BusinessCommissionBatchSaveOutDTO> saveList = JSONObject.parseObject(CommonUtil.defaultIfEmpty(redisTemplate.opsForValue().get(McnConstant.CACHE_PRIFIX + fileId)),
                            new TypeReference<List<BusinessCommissionBatchSaveOutDTO>>() {
                            });
                    ExcelUtils.exportExcel(CommonUtil.defaultList(saveList), title, BusinessCommissionBatchSaveOutDTO.class, title + ".xlsx", response);
                    break;
                case BUSINESS_COMMISSION_BATCH_DELETE:
                    title = "商务提成-批量删除失败原因";
                    List<BusinessCommissionBatchDeleteOutDTO> deleteList = JSONObject.parseObject(CommonUtil.defaultIfEmpty(redisTemplate.opsForValue().get(McnConstant.CACHE_PRIFIX + fileId)),
                            new TypeReference<List<BusinessCommissionBatchDeleteOutDTO>>() {
                            });
                    ExcelUtils.exportExcel(CommonUtil.defaultList(deleteList), title, BusinessCommissionBatchDeleteOutDTO.class, title + ".xlsx", response);
                    break;
                default:
                    throw new BusinessException(McnErrorCode.EXPORT_FILE_ID_ILLEGAL);
            }
            redisTemplate.delete(McnConstant.CACHE_PRIFIX + fileId);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * @param input
     * @param incomeContractMap
     * @return failedReason
     */
    private String verifyExcelImportAdd(BusinessCommissionBatchSaveDTO input, Map<String, IncomeContract> incomeContractMap, Map<String, SUserVo> userMap) {
        StringBuffer failedReason = new StringBuffer();
        if (incomeContractMap == null) {
            incomeContractMap = new HashMap<>(0);
        }
        if (userMap == null) {
            userMap = new HashMap<>(0);
        }
        refactor(input, incomeContractMap, failedReason);
        if (StringUtils.isBlank(input.getCommissionName())) {
            failedReason.append("提成人必填").append(SEPARATOR);
        } else {
            if (!userMap.containsKey(input.getCommissionName())) {
                failedReason.append("找不到提成人").append(SEPARATOR);
            }
        }

        if (input.getPersonalCommission() == null) {
            failedReason.append("个人提成必填").append(SEPARATOR);
        } else {
            if (input.getPersonalCommission().compareTo(BigDecimal.ZERO) == -1 || input.getPersonalCommission().scale() > NumberCst.TWO.intValue()) {
                failedReason.append("请正确录入数值-个人提成>=0，最多含两位小数").append(SEPARATOR);
            }
        }
        if (StringUtils.isBlank(input.getDepartmentHeadName())) {
            failedReason.append("部门负责人必填").append(SEPARATOR);
        } else {
            if (!userMap.containsKey(input.getDepartmentHeadName())) {
                failedReason.append("找不到部门负责人").append(SEPARATOR);
            }
        }

        if (input.getDepartmentHeadCommissionPoint() == null) {
            failedReason.append("部门负责人提点必填").append(SEPARATOR);
        } else {
            if (input.getDepartmentHeadCommissionPoint().compareTo(BigDecimal.ZERO) == -1 || input.getDepartmentHeadCommissionPoint().compareTo(BigDecimal.ONE) == 1 || input.getDepartmentHeadCommissionPoint().scale() > NumberCst.FOUR.intValue()) {
                failedReason.append("请正确录入百分比，0%<=部门负责人提点<=100%，最多含两位小数").append(SEPARATOR);
            }
        }
        if (input.getDepartmentHeadCommission() == null) {
            failedReason.append("部门负责人提成必填").append(SEPARATOR);
        } else {
            if (input.getDepartmentHeadCommission().compareTo(BigDecimal.ZERO) == -1 || input.getDepartmentHeadCommission().scale() > NumberCst.TWO.intValue()) {
                failedReason.append("请正确录入数值-部门负责人提成>=0，最多含两位小数").append(SEPARATOR);
            }
        }
        int maxLength = 200;
        if (StringUtils.isNotBlank(input.getRemark()) && input.getRemark().length() > maxLength) {
            failedReason.append("请输入200字符长度备注").append(SEPARATOR);
        }
        if (failedReason.length() == 0) {
            return null;
        } else if (failedReason.toString().endsWith(SEPARATOR)) {
            return failedReason.substring(0, failedReason.length() - 1);
        }
        return failedReason.toString();
    }

    private void refactor(BusinessCommissionBatchSaveDTO input, Map<String, IncomeContract> incomeContractMap, StringBuffer failedReason) {
        if (StringUtils.isBlank(input.getContractCode())) {
            failedReason.append("合同编号必填").append(SEPARATOR);
        } else {
            IncomeContract incomeContract = incomeContractMap.get(input.getContractCode());
            if (incomeContract == null) {
                failedReason.append("请录入正确的合同编号").append(SEPARATOR);
            } else if (!ApprovalStatusEnum.isPassed(incomeContract.getApprovalStatus())) {
                failedReason.append("合同单据状态须为审批通过").append(SEPARATOR);
            } else if (!NumberCst.TWO.equals(incomeContract.getPayBackStatus())) {
                failedReason.append("合同回款状态须为已回款").append(SEPARATOR);
            }
        }
        if (input.getGeneralPoints() == null) {
            failedReason.append("个人总提点必填").append(SEPARATOR);
        } else {
            if (input.getGeneralPoints().compareTo(BigDecimal.ZERO) == -1 || input.getGeneralPoints().compareTo(BigDecimal.ONE) == 1 || input.getGeneralPoints().scale() > NumberCst.FOUR.intValue()) {
                failedReason.append("请正确录入百分比，0%<=个人总提点<=100%，最多含两位小数").append(SEPARATOR);
            }
        }
        if (input.getTargetAchievementRate() == null) {
            failedReason.append("客户目标达成率必填").append(SEPARATOR);
        } else {
            if (input.getTargetAchievementRate().compareTo(BigDecimal.ZERO) == -1 || input.getTargetAchievementRate().compareTo(BigDecimal.ONE) == 1 || input.getTargetAchievementRate().scale() > NumberCst.FOUR.intValue()) {
                failedReason.append("请正确录入百分比，0%<=客户目标达成率<=100%，最多含两位小数").append(SEPARATOR);
            }
        }
    }

    /**
     * @param detailList
     * @param qiMap
     * @param context
     */
    @SneakyThrows
    private void extendBusinessCommissionDetail(List<BusinessCommissionDetail> detailList, Map<String, QuarterIncomeContractVO> qiMap, Map<String, SUserVo> userMap, BusinessCommissionRuleContext context) {
        Map<String, BusinessCommissionReturn> returnMap = new HashMap<>(detailList.size());
        try {
            final Date v2StartDate = DateUtils.parseDate(earliestStartDateStr, McnConstant.LONG_DATE_FORMAT);
            detailList.forEach(detail -> {
                QuarterIncomeContractVO x = qiMap.get(detail.getIncomeCode());
                SUserVo sUserVo = userMap.get(detail.getCommissionName());
                BigDecimal projectSales = x.getBusinessAmount().multiply(PERCENT_30);
                if (!x.getCreateDate().before(v2StartDate)) {
                    String key = StringUtils.joinWith("_", x.getTenantId(), x.getCompanyId(), x.getDepartmentId(), x.getQuarterCode());
                    if (!returnMap.containsKey(key)) {
                        BusinessCommissionReturn bcReturn = bcReturnMapper.selectOne(Wrappers.lambdaQuery(BusinessCommissionReturn.class)
                                .eq(BusinessCommissionReturn::getTenantId, x.getTenantId()).eq(BusinessCommissionReturn::getCompanyId, x.getCompanyId())
                                .eq(BusinessCommissionReturn::getDepartmentId, x.getDepartmentId()).eq(BusinessCommissionReturn::getQuarterCode, x.getQuarterCode()));
                        if (bcReturn != null) {
                            returnMap.put(key, bcReturn);
                        }
                    }
                    BusinessCommissionReturn bcReturn = returnMap.get(key);
                    detail.setReturnRate(Objects.nonNull(bcReturn) ? bcReturn.getReturnRate() : BigDecimal.ONE);
                    detail.setReturnFactor(Objects.nonNull(bcReturn) ? bcReturn.getReturnFactor() : BigDecimal.ONE);
                }
                detail.setProjectSales(projectSales.setScale(2, BigDecimal.ROUND_HALF_UP));
                CustomerTarget customerTarget = context.getCustomerTarget(x.getQuarterCode(), x.getCustomerId());
                detail.setKeyCustomers(Objects.nonNull(customerTarget) ? NumberCst.ZERO : NumberCst.ONE);
                if (!NumberCst.ZERO.equals(detail.getKeyCustomers())) {
                    //客户目标达成率，非重点客户-取不到就默认100%
                    detail.setTargetAchievementRate(BigDecimal.ONE);
                }
                DepartmentTarget departmentTarget = context.getDepartmentTarget(x.getQuarterCode(), x.getDepartmentId());
                detail.setDepartmentTargetAchievementRate(Objects.nonNull(departmentTarget) ? departmentTarget.getTargetReachRate() : BigDecimal.ONE);
                BaseCustomer baseCustomer = context.getBaseCustomer(x.getCustomerId());
                if (baseCustomer != null) {
                    detail.setCustomerScore(baseCustomer.getCustomerScore());
                }
                detail.setIsConfirmed(NumberCst.ZERO);
                detail.setIsInvalid(NumberCst.ZERO);
                detail.setIsDelete(NumberCst.ZERO);
                detail.setCreateDate(x.getCreateDate());
            });
        } finally {
            context.clear();
            qiMap.clear();
            returnMap.clear();
        }
    }
}
